<?php
/**
 * @version 		$Id$
 * @author 			Luu Trong Hieu<tronghieu1012@yahoo.com>
 * @copyright 		Copyright (c) 2010 Luu Trong Hieu. All right reserved.
 * @license 		GNU/GPL. see license.php
 */
defined('IN_FLYWHEEL') or die('Restricted Access');
/**
 * fWebApplication
 * 	base of web application
 * 
 * @package 	system
 * @subpackage 	application
 *
 */
class fWebApplication extends fApplication  {
	/**
	 * Web page layout template
	 *
	 * @var string
	 */	
	protected $_layout = null;
	
	protected $_configuration;
	
	/**	 
	 *
	 * @var fController
	 */
	protected $_controller;
	/**
	 * Construct new fWebApplication object
	 *
	 */
	public function __construct($name) {
		$this->name = $name;
		//Set log eviroment
		if (fConfig::get('enviroment') == parent::ENV_DEV 
				|| fConfig::get('environment') == parent::ENV_TEST) {
			fConfig::set('log', true);
		}
		else {
			fConfig::set('log', false);
		}				
	}
	
	/**
	 * Initialize
	 * 
	 * @return void
	 * @throws fConfigException
	 */
	protected function _init() {
		bootstrapping($this->name);
		//define controller and modules path
		define('_APP_PATH_', _APPS_PATH_.$this->name._DS_);
		define('_CONTROLLERS_PATH_', _APP_PATH_.'controllers'._DS_);
		define('_MODULES_PATH_', _APP_PATH_.'modules'._DS_);
		define('_APP_CONFIGURATION_PATH_', _APP_PATH_.'config'._DS_);
		define('_APP_TEMPLATES_PATH_', _APP_PATH_.'templates'._DS_);
		define('_APP_LANGUAGE_PATH_', _LANGUAGES_PATH_.$this->name._DS_);
		
		$this->_configuration = new fApplicationConfiguration();
		$this->_configuration->initConfiguration();
        fBoostraper::loadDoctrine();
		
		fFactory::getSession();
		$this->_authorize();		
	}
	
	/**
	 * Run application
	 *
	 */
	public function run() {
		if (fConfig::get('debug')) {
			fProfiler::getInstance()->mark('Begin run web application', 'system.' . get_class($this));
		}
		$buffer = $this->_loadController();						
		$renderMode = $this->_controller->getRenderMode();	
		switch ($renderMode) {
			case 'TEXT':				
			case 'PARTIAL':
				$response = fFactory::getResponse();
				$response->setBody($buffer);
				$response->send();
				break;
			case 'COMPONENT':
				$this->_renderPage($buffer);				
				break;
			default:
				break;				
		}		
	}
	
	protected function _renderPage($buffer) {		
		$document = fFactory::getDocument();
		$response = fFactory::getResponse();
		$document->setBuffer($buffer, 'component');
		$template = fFactory::getTemplate();
		//Assign global object
		$template->assign('document', $document);        
		if ($this->_layout == null) {			
			$config = fConfig::get('template');
			$this->_layout = (isset($config['default_layout']))? 
							$config['default_layout']: 'default'; //load default layout				
		}
					
		ob_start();
		ob_implicit_flush(0);
		try	{			
			$template->display($this->_layout);
			if (fConfig::get('debug')) {
				fProfiler::getInstance()->mark('Template display', 'system.'.get_class($this));
			}
		}
		catch (Exception $e) {
			ob_end_clean();
			throw new fException($e);
		}
		$content = ob_get_clean();		
		if (fConfig::get('debug')) {
			$count = 0;
			$debug = fProfiler::debug();
			$content = str_ireplace('</body>', $debug .'</body>', $content, $count);
			if (!$count) {
				$content .= $debug; 			
			}
		}
		
		$response->setBody($content);
		$response->send();
	}
	
	/**
	 * Load Controller
	 */
	private function _loadController() {
		fFactory::getI18N()->getLanguageSource()->import('common');
		$controllerName = fFactory::getRouter()->getController();		

		if (!file_exists($file = _CONTROLLERS_PATH_.$controllerName._DS_.$controllerName.'.controller.php')) {
			throw new fControllerException('Controller "' .$controllerName .'" does not exist!');
		}
		
		require_once $file;
		$className = $controllerName.'Controller';
		$this->_controller = new $className($controllerName);		
		return $this->_controller->execute();
	}
	
	/**
	 * Get Configuration Object
	 *
	 * @return fApplication Configuration
	 */
	public function getConfiguration() {
		return $this->_configuration;
	}
	
	/**
	 * get Layout
	 *
	 * @return string
	 */
	public function getLayout() {
		return $this->_layout;
	}
	
	/**
	 * Set layout
	 *
	 * @param string $s
	 */
	public function setLayout($s) {
		$this->_layout = $s;
	}
	
	/**
	 * Check authenticate
	 *
	 */
	protected function _authorize() {		
		$config = fConfig::get('secure');
		$user = fFactory::getUser();		
		if ($config['login_required'] == 1 && $user->isAuthenticated() === false) {//Application require login
			$router = fFactory::getRouter();	
			$inLoginAction = false;
			
			if ($config['login_component'] == $router->getComponentName()) {
				$inLoginAction = true;
			}
			if ($config['login_action'] != null && ($router->getAction() != $config['login_action'])) {
				$inLoginAction = false;
			}
			
			if (!$inLoginAction && fConfig::has($config['login_component'], 'routing')) {				
				$remap = fConfig::get($config['login_component'], 'routing');
				if ($remap['controller'] == $router->getController()) {
					$inLoginAction = true;									
				}				
				if (!isset($remap['action']) && !is_null($config['login_action'])) {
					if ($router->getAction() == $config['login_action']) {
						$inLoginAction = true;				
					}
				}
			}
						
			if (!fFactory::getUser()->isAuthenticated() && !$inLoginAction) { // Neu chua login redirect toi component va action login
					$url = fUri::createUrl($config['login_component'], $config['login_action']);								
					fRequest::redirect($url);//redirect
			}
		}
		if ($this->debug) {
			fProfiler::getInstance()->mark('Authorize', 'system.'.get_class($this));
		}
	}
}